﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using WxPayAPI;
using Yule8xCommon.Applib;
using Yule8xCommon.Db;
using Yule8xCommon.Typelib;

namespace Yule8xModel
{
    public class UserModels
    {
        /// <summary>
        /// 动态设置用户微信登录信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="fields"></param>
        /// <param name="wxUser"></param>
        /// <param name="action"></param>
        public static void SetWxUserProperty(int uid, string fields, WxUserInfoResult wxUser, Action<WxUserInfoResult, DataRow> action)
        {
            string sqlstmt = string.Format("select {0} from t_user where user_id={1}", fields, uid);
            DataTable dtUser = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(sqlstmt);
            if (dtUser.Rows.Count < 1)
            {
                return;
            }
            action(wxUser, dtUser.Rows[0]);
        }

        public static WxUserInfoResult GetWxUserInfo(int user_id)
        {
            string sqlstmt = string.Format("select subscribe,openid_biz as openid,nickname,sex,'zh-cn' as language,city,province,country,headimgurl,subscribe_time,unionid,remark,groupid,tagid_list,user_id,game_id_bozhong,game_id_wanghu,parent1_uid,parent2_uid,realname from t_user  where user_id={0}", user_id);
            DataTable dtUser = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(sqlstmt);
            if (dtUser.Rows.Count < 1)
            {
                return null;
            }
            WxUserInfoResult user;
            try
            {
                user = new WxUserInfoResult();

                user.subscribe = (short)dtUser.Rows[0]["subscribe"];
                user.openid = dtUser.Rows[0]["openid"].ToString();
                user.nickname = dtUser.Rows[0]["nickname"].ToString();
                user.sex = (short)dtUser.Rows[0]["sex"];
                user.language = dtUser.Rows[0]["language"].ToString();
                user.city = dtUser.Rows[0]["city"].ToString();
                user.province = dtUser.Rows[0]["province"].ToString();
                user.country = dtUser.Rows[0]["country"].ToString();
                user.headimgurl = dtUser.Rows[0]["headimgurl"].ToString();
                user.subscribe_time = (int)dtUser.Rows[0]["subscribe_time"];
                user.unionid = dtUser.Rows[0]["unionid"].ToString();
                user.remark = dtUser.Rows[0]["remark"].ToString();
                user.groupid = (int)dtUser.Rows[0]["groupid"];
                user.tagid_list = dtUser.Rows[0]["tagid_list"].ToString();
                user.user_id = (int)dtUser.Rows[0]["user_id"];
                user.game_id_bozhong = (int)dtUser.Rows[0]["game_id_bozhong"];
                user.game_id_wanghu = (int)dtUser.Rows[0]["game_id_wanghu"];
                user.parent1_uid = (int)dtUser.Rows[0]["parent1_uid"];
                user.parent2_uid = (int)dtUser.Rows[0]["parent2_uid"];
                user.realname = DataTableUtil.GetString(dtUser, "realname");

                return user;
            }
            catch (Exception ex)
            {
                ResponseUtil.WriteEnd(ex.Message);
            }
            ResponseUtil.WriteEnd(sqlstmt);
            return null;
        }

        internal static string GetNickName(int user_id)
        {
            string sqlstmt = string.Format("select nickname from t_user where user_id={0}", user_id);
            object ovalue = DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt);
            return null == ovalue ? string.Empty : ovalue.ToString();
        }

        public static bool CheckSubscribeWechat(int user_id)
        {
            string sqlstmt = string.Format("select count(0) from t_user where user_id={0} and subscribe=1 and subscribe_time>10", user_id);
            int count = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteCount(sqlstmt);
            return count > 0;
        }

        public static string GetMobile(int user_id, bool mask = false)
        {
            string sqlstmt = string.Format("select mobile from t_user where user_id={0}", user_id);
            string mobile = DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt, string.Empty).ToString();
            if (mask && mobile.Length > 10)
            {
                mobile = string.Format("{0}*****{1}", mobile.Substring(0, 2), mobile.Substring(mobile.Length - 3));
            }
            return mobile;
        }

        /// <summary>
        /// 每天数据库当日统计清零操作
        /// </summary>
        public static bool StaticsDailyReset()
        {
            string return_id = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddReturn("@return");
            System.Data.Common.DbParameter[] outParams = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteProcedureNonQuery("proc_reset_daily_statistics_report", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@return")
                {
                    return_id = p.Value.ToString();
                    continue;
                }
            }
            LogUtil.Instance.WriteInfo(string.Format("[每天数据库当日统计清零操作] result={0}", return_id));
            int iout;
            if (int.TryParse(return_id, out iout))
            {
                return iout > 0;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 更新用户上级代理资料
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="parent1_uid"></param>
        public static bool UpdateUserParent1Info(int user_id, int parent1_uid, out string outMsg)
        {
            outMsg = string.Empty;
            string sqlstmt = string.Format("select top 1 parent1_uid, top_agent_id from t_user where user_id={0}", parent1_uid);
            DataTable dtUser = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(sqlstmt);
            if (dtUser.Rows.Count < 1)
            {
                outMsg = string.Format("上级用户{0}不存在", parent1_uid);
                return false;
            }
            int parent2_uid = DataTableUtil.GetInteger(dtUser, "parent1_uid");
            int top_agent_id = DataTableUtil.GetInteger(dtUser, "top_agent_id");
            sqlstmt = string.Format("update t_user set parent1_uid={0}, parent2_uid={1}, top_agent_id={2} where user_id={3}", parent1_uid, parent2_uid, top_agent_id, user_id);
            int count=DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteNonQuery(sqlstmt);
            if (count < 1)
            {
                outMsg = string.Format("更新上级用户信息出错!");
            }
            return count > 0;
        }

        /// <summary>
        /// 实时获取钻石余额
        /// </summary>
        /// <param name="user_id"></param>
        /// <returns></returns>
        public static int GetDimondBlance(int user_id)
        {
            string sqlstmt = string.Format("select diamond_number from t_user_finance_account where user_id={0}", user_id);
            return int.Parse(DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt, "0").ToString());
        }

        /// <summary>
        /// 判断用户是否是代理
        /// <para>True=是代理;False=不是代理</para>
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public static bool CheckUserIsAgent(int uid)
        {
            string sqlstmt = string.Format("select count(0) from t_user where user_id={0} and is_agent=1", uid);
            return DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteCount(sqlstmt) > 0;
        }

        /// <summary>
        /// 用户注册成为代理申请操作
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="agent_regist_amount"></param>
        /// <param name="outTradeNo"></param>
        /// <param name="mobile"></param>
        /// <param name="realname"></param>
        /// <param name="parent1_uid"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool UserRegistAgentSubmit(int user_id, decimal agent_regist_amount, string outTradeNo, string mobile, string realname, int parent1_uid, string attach, out string msg)
        {
            if (string.IsNullOrEmpty(mobile) || string.IsNullOrEmpty(realname))
            {
                msg = "表单数据不完整!";
                return false;
            }
            // 判断顶级代理商，如果推荐人编号超过10万，则自动创建一条用户记录
            bool istopagent = false;
            int top_agent_id = 0;
            if (parent1_uid > 100000)
            {
                top_agent_id = parent1_uid;
                // 查询分销系统的顶级代理商表
                bool topagent_exists = UserModels.CheckTopAgentExists(top_agent_id);
                if (!topagent_exists)
                {
                    msg = string.Format("顶级代理商 [{0}] 不存在!", top_agent_id);
                    return false;
                }
                string outmsg;
                parent1_uid = UserModels.UserRegistTopAgent(top_agent_id, out outmsg); // parent1_uid修正为代理系统库的user_id
                if (parent1_uid < 1)
                {
                    msg = "创建顶级代理商出错!" + outmsg;
                    return false;
                }
                istopagent = true;
            }
            else
            {
                top_agent_id = UserModels.GetTopAgentId(parent1_uid);
            }
            if (top_agent_id < 1)
            {
                msg = string.Format("顶级代理商无效!", top_agent_id);
                return false;
            }
            string sqlstmt;
            int resultcount;

            // 更新数据库字段
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("mobile", mobile);
            data.Add("realname", realname);
            data.Add("top_agent_id", top_agent_id.ToString()); // 一定会有顶级代理商
            data.Add("parent1_uid", parent1_uid.ToString()); // 一定会有上级代理
            if (!istopagent)
            {
                sqlstmt = string.Format("select parent1_uid from t_user where user_id=" + parent1_uid);
                int parent2_uid = int.Parse(DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt, "0").ToString());
                data.Add("parent2_uid", parent2_uid.ToString());
            }
            sqlstmt = DbFactory.GetUpdateStatement("t_user", string.Format("user_id={0}", user_id), data);
            LogUtil.Instance.WriteInfo("[注册成为代理] 更新用户手机号码等资料 " + sqlstmt);
            resultcount = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteNonQuery(sqlstmt);
            if (resultcount < 1)
            {
                msg = "[注册成为代理] 更新用户手机号码等资料失败! " + sqlstmt;
                return false;
            }
            // 写入充值申请表
            data.Clear();
            data.Add("out_trade_no", outTradeNo);
            data.Add("amount", agent_regist_amount.ToString());
            data.Add("pay_channel", "wxpay");
            data.Add("user_id", user_id.ToString());
            data.Add("status", "0");
            data.Add("paramstr", attach);
            sqlstmt = DbFactory.GetInsertStatement("t_finance_recharge", data);
            resultcount = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteNonQuery(sqlstmt);
            msg = string.Format("[注册成为代理] 写入充值表 {0}:{1}", resultcount, sqlstmt);
            return resultcount > 0;
        }

        private static int GetTopAgentId(int parent1_uid)
        {
            string sqlstmt = string.Format("select top 1 top_agent_id from t_user where user_id={0}", parent1_uid);
            int top_agent_id = int.Parse(DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt, "0").ToString());
            return top_agent_id;
        }

        /// <summary>
        /// 判断顶级代理商是否存在
        /// <para>True=存在;False=不存在</para>
        /// </summary>
        /// <param name="top_agent_id"></param>
        /// <returns></returns>
        public static bool CheckTopAgentExists(int top_agent_id)
        {
            // insert into sy_user (user_id, USER_NAME, binding_ip, user_type) values (1018888, '1018888', '1', '3')
            string sqlstmt = string.Format("select count(0) from sy_user where USER_ID={0} and binding_ip='1' and user_type='3'", top_agent_id);
            int count = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteCount(sqlstmt);
            return count > 0;
        }

        /// <summary>
        /// 同步并获取GameID
        /// <para>成功返回GameID，失败返回0</para>
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="unionid"></param>
        /// <returns></returns>
        public static int GetGameID(int uid, string unionid, string game_mactcode, out string error)
        {
            error = string.Empty;
            // 获取本地代理数据库的gameid字段
            string where = null;
            if (uid > 0)
            {
                where = string.Format("user_id={0}", uid);
            }
            else if (!string.IsNullOrEmpty(unionid))
            {
                where = string.Format("unionid='{0}'", unionid);
            }
            if (null == where)
            {
                error = "传入参数无效";
                return 0;
            }
            string gameid_field = string.Empty;
            switch (game_mactcode)
            {
                case "bozhong":
                    gameid_field = "game_id_bozhong";
                    break;
                case "wanghu":
                    gameid_field = "game_id_wanghu";
                    break;
            }
            if (string.IsNullOrEmpty(gameid_field))
            {
                error = "游戏厂商未支持";
                return 0;
            }
            string sqlstmt = string.Format("select top 1 user_id, unionid, {0} from t_user where {1}", gameid_field, where);
            LogUtil.Instance.WriteInfo("[同步并获取GameID]: " + sqlstmt);
            DataTable dtUser = DbFactory.Init(AppInfo.conn_yule8x_agent, true).ExecuteDataTable(sqlstmt);
            if (dtUser.Rows.Count < 1)
            {
                error = "用户不存在,无须后续步骤，直接退出提高效率";
                return 0;
            }
            int gameid = int.Parse(dtUser.Rows[0][gameid_field].ToString());
            if (gameid < 1)
            {
                // 如果本地代理数据库没有gameid则通过游戏库连接来远程查询，因为上级可能下载了游戏，但未登录公众号，所以游戏id无法同步过来
                if (string.IsNullOrEmpty(unionid))
                {
                    unionid = dtUser.Rows[0]["unionid"].ToString();
                }
                switch (game_mactcode)
                {
                    case "bozhong":
                        gameid = BozhongGameUtil.GetGameID(unionid);
                        break;
                    case "wanghu":
                        gameid = WanghuGameUtil.GetGameID(unionid);
                        break;
                }
                if (gameid > 0)
                {
                    // 如果远程游戏数据库有gameid，则更新到本地代理数据库
                    sqlstmt = string.Format("update t_user set {0}={1} where unionid='{2}'", gameid_field, gameid, unionid);
                    DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteNonQuery(sqlstmt);
                    LogUtil.Instance.WriteInfo("[同步并获取GameUID]:" + sqlstmt);
                }
            }
            return gameid;
        }

        /// <summary>
        /// 获取用户账户的实时余额
        /// </summary>
        /// <param name="user_id"></param>
        /// <returns></returns>
        public static decimal GetUserAccountBlance(int user_id)
        {
            string sqlstmt = string.Format("select blance from t_user_finance_account where user_id={0}", user_id);
            string strvalue = DbFactory.Init(AppInfo.conn_yule8x_agent).GetValue(sqlstmt, "0").ToString();
            return decimal.Parse(strvalue);
        }

        /// <summary>
        /// 获取用户代理表和代理统计表的记录
        /// </summary>
        /// <param name="user_id"></param>
        /// <returns></returns>
        public static DataTable GetUserAgentStatistcs(int user_id)
        {
            string sqlstmt = string.Format("select top 1 s.*, a.agent_type from t_user_agent a left join t_user_agent_statistics s on a.user_id=s.user_id where a.user_id={0}", user_id);
            return DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(sqlstmt);
        }

        /// <summary>
        /// 获取用户资金账户表和资金账户统计表的记录
        /// </summary>
        /// <param name="user_id"></param>
        /// <returns></returns>
        public static DataTable GetUserFinanceAccountStatistcs(int user_id)
        {
            string sqlstmt = string.Format("select top 1 a.blance, a.diamond_number, s.* from t_user_finance_account a left join t_user_finance_statistics s on a.user_id=s.user_id where a.user_id={0}", user_id);
            return DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(sqlstmt);
        }

        /// <summary>
        /// 微信获取用户基本信息回调页面，并更新基本信息到用户表
        /// <para>返回用户表user_id</para>
        /// </summary>
        /// <param name="wxUser"></param>
        /// <returns></returns>
        public static int WxLoginCallbackUpdateDb(WxUserInfoResult wxUser, int referral_id)
        {
            // 获取用户基本信息（包括UnionID机制）
            // 成功：{ "subscribe": 1, "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "Band", "sex": 1, "language": "zh_CN", "city": "广州", "province": "广东", "country": "中国", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", "subscribe_time": 1382694957, "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" "remark": "", "groupid": 0, "tagid_list": [128, 2]}
            // 错误：{"errcode":40013,"errmsg":"invalid appid"}
            // 判断是否已注册，否则自动注册
            // 测试的时候会清空数据库用户表，这时候如果用户已经关注公众号了，所以不会通过subscribe事件来重新注册用户，只能在登录回调事件重新注册用户
            string sqlstmt = string.Format("select count(0) from t_user where openid_biz='{0}'", wxUser.openid);
            int count = DbFactory.Init(AppInfo.conn_yule8x_agent, true).ExecuteCount(sqlstmt);
            string wxstr = JSON.stringify(wxUser);
            LogUtil.Instance.WriteInfo(string.Format("[LoginCallBack] WxLoginCallbackUpdateDb-获取用户基本信息时判断用户是否需要重新注册：count={0}, sql={1}, str={2}", count, sqlstmt, wxstr));
            int uid = 0;
            // 重新注册用户
            if (count < 1)
            {
                string returnMsg;
                uid = UserRegistByQrcode(wxUser.openid, 0, referral_id, 0, 0, "bozhong", out returnMsg);
                LogUtil.Instance.WriteInfo(string.Format("[LoginCallBack] WxLoginCallbackUpdateDb-获取用户基本信息时重新注册用户 uid={0},openid={1},referral_id={2},result={3},str={4} ", uid, wxUser.openid, referral_id, (uid < 1 ? "注册失败!" : "注册成功"), wxstr));
                // 从这里注册的，
            }
            if (uid < 1)
            {
                sqlstmt = string.Format("select top 1 user_id from t_user where unionid='{0}'", wxUser.unionid);
                uid = int.Parse(DbFactory.Instance.GetValue(sqlstmt, "0").ToString());
            }
            if (string.IsNullOrEmpty(wxUser.nickname))
            {
                LogUtil.Instance.WriteInfo(string.Format("[LoginCallBack] WxLoginCallbackUpdateDb-Nickname为空，不更新，直接退出!uid={0},openid={1},str={2}", uid, wxUser.openid, wxstr));
                return uid;
            }
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("nickname", wxUser.nickname);
            data.Add("sex", wxUser.sex.ToString());
            data.Add("city", wxUser.city);
            data.Add("province", wxUser.province);
            data.Add("country", wxUser.country);
            data.Add("headimgurl", wxUser.headimgurl);
            data.Add("unionid", wxUser.unionid);
            data.Add("remark", wxUser.remark);
            data.Add("groupid", wxUser.groupid.ToString());
            data.Add("tagid_list", wxUser.tagid_list);
            sqlstmt = DbFactory.GetUpdateStatement("t_user", string.Format("openid_biz='{0}'", wxUser.openid), data);
            count = DbFactory.Instance.ExecuteNonQuery(sqlstmt);
            LogUtil.Instance.WriteInfo(string.Format("[LoginCallBack] WxLoginCallbackUpdateDb-获取用户基本信息时更新 uid={0}, openid={1},result={2}, sql={3}, str={4}", uid, wxUser.openid, (count > 0 ? "成功" : "失败"), sqlstmt, wxstr));
            if (uid < 1)
            {
                sqlstmt = string.Format("select top 1 user_id from t_user where unionid='{0}'", wxUser.unionid);
                uid = int.Parse(DbFactory.Instance.GetValue(sqlstmt, "0").ToString());
            }
            return uid;
        }

        /// <summary>
        /// 用户取消关注微信公众号
        /// </summary>
        /// <param name="openid"></param>
        public static int UserUnsubscribe(string openid, int unsubscribe_time, out string output_msg)
        {
            output_msg = string.Empty;
            if (string.IsNullOrEmpty(openid))
            {
                return 0;
            }
            string userid = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddValue<string>("@pstr_openid_biz", openid);
            dbParams.AddValue<int>("@pint_timestamp", unsubscribe_time);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            System.Data.Common.DbParameter[] outParams = DbFactory.Instance.ExecuteProcedureNonQuery("proc_user_unsubscribe_wechat", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@pstr_output")
                {
                    output_msg = p.Value.ToString();
                    continue;
                }
                if (p.ParameterName == "@return")
                {
                    userid = p.Value.ToString();
                    continue;
                }
            }
            LogUtil.Instance.WriteInfo(string.Format("[用户取消关注微信公众号] uid={0}, returnmsg={1}, openid={2}", userid, output_msg, openid));
            int iuserid;
            return int.TryParse(userid, out iuserid) ? iuserid : 0;
        }

        /// <summary>
        /// 用户关注微信号并注册(无扫描推广码)
        /// <para>返回用户注册的user_id</para>
        /// </summary>
        /// <param name="openid"></param>
        /// <param name="output_msg"></param>
        public static int UserRegistWithoutQrcode(string openid, int subscribe_time, out string output_msg)
        {
            output_msg = string.Empty;
            string userid = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddValue<string>("@pstr_openid_biz", openid);
            dbParams.AddValue<int>("@pint_timestamp", subscribe_time);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            try
            {
                System.Data.Common.DbParameter[] outParams = DbFactory.Instance.ExecuteProcedureNonQuery("proc_user_regist_without_qrcode", dbParams.ToArray());
                foreach (System.Data.Common.DbParameter p in outParams)
                {
                    if (p.ParameterName == "@pstr_output")
                    {
                        output_msg = p.Value.ToString();
                        continue;
                    }
                    if (p.ParameterName == "@return")
                    {
                        userid = p.Value.ToString();
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            bool result = (output_msg.IndexOf("SUCCESS") > -1);
            // 记录日志
            LogUtil.Instance.WriteInfo(string.Format("[用户关注微信号并注册(无扫描推广码)] user_id={0}, returnmsg={1}, openid={2}", userid, output_msg, openid));

            if (!result)
            {
                LogUtil.Instance.WriteInfo("[用户关注微信号并注册(无扫描推广码)] 订阅时帐号已存在!");
            }
            int iuserid;
            return int.TryParse(userid, out iuserid) ? iuserid : 0;
        }
        /// <summary>
        /// 用户关注微信号并注册(扫描推广码)
        /// <para>返回用户注册的user_id</para>
        /// </summary>
        /// <param name="openid"></param>
        /// <param name="parent1_uid"></param>
        /// <param name="dailycardcount">配置参数中的用户每天推广领卡最大数量</param>
        /// <param name="eachcardcount">配置参数中的每推广一个用户可获得的房卡数量</param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        public static int UserRegistByQrcode(string openid, int subscribe_time, int parent1_uid, int dailycardcount, int eachcardcount, string game_mactcode, out string output_msg)
        {
            output_msg = string.Empty;
            string userid = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddValue<string>("@pstr_openid_biz", openid);
            dbParams.AddValue<int>("@pint_timestamp", subscribe_time);
            dbParams.AddValue<int>("@pint_parent1_uid", parent1_uid);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            System.Data.Common.DbParameter[] outParams = DbFactory.Instance.ExecuteProcedureNonQuery("proc_user_regist_with_qrcode", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@pstr_output")
                {
                    output_msg = p.Value.ToString();
                    continue;
                }
                if (p.ParameterName == "@return")
                {
                    userid = p.Value.ToString();
                    continue;
                }
            }
            bool result = (output_msg.IndexOf("SUCCESS") > -1);
            // 记录日志
            LogUtil.Instance.WriteInfo(string.Format("[用户关注微信号并注册(扫描推广码)] user_id={0}, parent1_uid={1}, returnmsg={2}, openid={3}", userid, parent1_uid, output_msg, openid));

            if (result)
            {
                if (eachcardcount > 0)
                {
                    UserModels.RefereralUserGetCard(openid, parent1_uid, dailycardcount, eachcardcount, game_mactcode);
                }
            }
            else
            {
                LogUtil.Instance.WriteInfo("[用户关注微信号并注册(扫描推广码)] 订阅时帐号已存在!");
            }
            int iuserid;
            return int.TryParse(userid, out iuserid) ? iuserid : 0;
        }

        /// <summary>
        /// 注册顶级代理商
        /// <para>返回用户注册的user_id</para>
        /// </summary>
        /// <param name="top_agent_id"></param>
        /// <param name="output_msg"></param>
        public static int UserRegistTopAgent(int top_agent_id, out string output_msg)
        {
            output_msg = string.Empty;
            string userid = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddInputInteger("@pint_top_agent_id", top_agent_id);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            System.Data.Common.DbParameter[] outParams = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteProcedureNonQuery("proc_user_regist_topagent", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@pstr_output")
                {
                    output_msg = p.Value.ToString();
                    continue;
                }
                if (p.ParameterName == "@return")
                {
                    userid = p.Value.ToString();
                    continue;
                }
            }
            bool result = (output_msg.IndexOf("SUCCESS") > -1);
            // 记录日志
            LogUtil.Instance.WriteInfo(string.Format("[注册顶级代理商] user_id={0}, returnmsg={1}", top_agent_id, output_msg));

            if (!result)
            {
                LogUtil.Instance.WriteInfo(string.Format("[注册顶级代理商] user_id={0}, 帐号已存在!", top_agent_id));
            }
            int iuserid;
            return int.TryParse(userid, out iuserid) ? iuserid : 0;
        }


        /// <summary>
        /// 推广用户注册，上级用户领卡
        /// </summary>
        /// <param name="openid"></param>
        /// <param name="parent1_uid"></param>
        /// <param name="dailycardcount">配置参数中的用户每天推广领卡最大数量</param>
        /// <param name="eachcardcount">配置参数中的每推广一个用户可获得的房卡数量</param>
        /// <param name="game_mactcode"></param>
        public static void RefereralUserGetCard(string openid, int parent1_uid, int dailycardcount, int eachcardcount, string game_mactcode)
        {
            // 用户注册后，上级获得1颗钻石，用户取消关注后，即时再关注，不管上级是否相同，新的上级都不会再获得钻石，防止用户通过取消关注来刷卡
            string sqlstmt = string.Format("select count(0) from t_user where openid_biz='{0}' and parent1_awards_status=1", openid);
            if (DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteCount(sqlstmt) > 0)
            {
                return;
            }
            // 上级推广可以获得n颗钻石
            string error;
            int gameid = UserModels.GetGameID(parent1_uid, null, game_mactcode, out error);
            if (gameid > 0) // 如果上级有gameid，进入推广领卡流程
            {
                string today = DateTime.Today.ToString("yyyy-MM-dd");
                // 获取每日最大推广领卡数量上限
                sqlstmt = string.Format("select referral_user_daily_card_number from t_user  where user_id={0} and login_date='{1}'", parent1_uid, today);
                object ovalue = DbFactory.Instance.GetValue(sqlstmt);
                if (null == ovalue)
                {
                    // 新的一天，满血复活（没有当天记录）
                    dailycardcount = dailycardcount - eachcardcount;
                    // 上级用户每日可赠卡数量减少
                    sqlstmt = string.Format("update t_user set referral_user_daily_card_number={0} where user_id={1}", dailycardcount, parent1_uid);
                    DbFactory.Instance.ExecuteNonQuery(sqlstmt);
                    // 增加到游戏服务器数据库中
                    BozhongGameUtil.UpdateRoomCard(gameid, eachcardcount);
                }
                else
                {
                    dailycardcount = int.Parse(ovalue.ToString()) - eachcardcount;
                    if (dailycardcount >= 0) // 今天还可以领卡
                    {
                        // 上级用户每日可赠卡数量减少
                        sqlstmt = string.Format("update t_user set referral_user_daily_card_number={0} where user_id={1}", dailycardcount, parent1_uid);
                        DbFactory.Instance.ExecuteNonQuery(sqlstmt);
                        // 增加到游戏服务器数据库中
                        BozhongGameUtil.UpdateRoomCard(gameid, eachcardcount);
                    }
                }
                // 用户注册后，上级获得1颗钻石，用户取消关注后，即时再关注，不管上级是否相同，新的上级都不会再获得钻石，防止用户通过取消关注来刷卡
                sqlstmt = string.Format("update t_user set parent1_awards_status=1 where openid_biz='{0}'", openid);
                DbFactory.Instance.ExecuteNonQuery(sqlstmt);
            }
        }
        /// <summary>
        /// 用户每日领卡
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="date"></param>
        /// <param name="number"></param>
        /// <param name="game_id"></param>
        /// <param name="game_mact_id"></param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        public static bool UserDailyGetDimond(int uid, DateTime date, int number, int game_currency_number, int game_id, int game_mact_id, out string output_msg)
        {
            output_msg = string.Empty;
            string userid = string.Empty;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddValue<int>("@pint_uid", uid);
            dbParams.AddValue<int>("@pint_dimond_number", number);
            dbParams.AddValue<string>("@pstr_date", date.ToString("yyyy-MM-dd"));
            dbParams.AddValue<int>("@pint_game_id", game_id);
            dbParams.AddValue<int>("@pint_game_mact_id", game_mact_id);
            dbParams.AddOutput<string>("@pstr_output");
            System.Data.Common.DbParameter[] outParams = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteProcedureNonQuery("proc_daily_get_diamond", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@pstr_output")
                {
                    output_msg = p.Value.ToString();
                    continue;
                }
            }
            bool result = (output_msg.IndexOf("SUCCESS") > -1);
            if (result)
            {
                switch (game_mact_id)
                {
                    case 1:
                        // 更新泊众房卡
                        result = BozhongGameUtil.UpdateRoomCard(game_id, game_currency_number);
                        if (!result)
                        {
                            output_msg = "[用户免费领钻] 更新泊众房卡数据出错：" + output_msg;
                            LogUtil.Instance.WriteError(output_msg, null);
                        }
                        break;
                    case 2:
                        // 更新网狐游戏豆
                        GameUserInfoModel wanghuuser = WanghuGameUtil.GetGameUserInfo(game_id);
                        if (null == wanghuuser)
                        {
                            output_msg = "[用户免费领钻] 更新网狐游戏豆数据出错：用户不存在, game_uid=" + game_id;
                            LogUtil.Instance.WriteError(output_msg, null);
                        }
                        else
                        {
                            result = WanghuGameUtil.UpdateYouxidou(wanghuuser.UserID, wanghuuser.Accounts, game_currency_number, out output_msg);
                            if (!result)
                            {
                                output_msg = "[用户免费领钻] 更新网狐游戏豆数据出错：" + output_msg;
                                LogUtil.Instance.WriteError(output_msg, null);
                            }
                        }
                        break;
                }
            }
            return result;
        }
        /// <summary>
        /// 获取用户每日推广领卡剩余的最大数量
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="date"></param>
        /// <param name="number"></param>
        /// <returns></returns>
        public static int GetReferralUserDailyMaxNumber(int uid, DateTime date, int number)
        {
            // 如果不是今天，则把最大领卡数量重置为配置的初始值, 日期改为今天
            string sqlstmt = string.Format("update t_user set referral_user_daily_card_number = {0}, login_date = '{1}' where user_id = {2} and login_date <> '{1}';", number, date.ToString("yyyy-MM-dd"), uid);
            DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteNonQuery(sqlstmt);
            // 获取今天的最大数量
            sqlstmt = string.Format("select referral_user_daily_card_number from t_user where user_id = {0};", uid);
            return int.Parse(DbFactory.Instance.GetValue(sqlstmt, "0").ToString());
        }

        /// <summary>
        /// 判断用户每日领卡状态
        /// <para>True=已领卡; False=未领卡</para>
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public static bool CheckUserDailyDrawDimondStatus(int uid)
        {
            string sqlstmt = string.Format("select count(0) from t_finance_transaction_details where user_id={0} and daily_draw_card_status=1", uid, DateTime.Today.ToString("yyyy-MM-dd"));
            int count = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteCount(sqlstmt);
            return count > 0;
        }
        /// <summary>
        /// 注册成为代理支付流程
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="payamount"></param>
        /// <param name="dimond_number"></param>
        /// <param name="rebate_amount"></param>
        /// <param name="parent1_amount"></param>
        /// <param name="parent2_amount"></param>
        /// <param name="encrypt_key"></param>
        /// <param name="out_trade_no"></param>
        /// <param name="pay_channel"></param>
        /// <param name="paramstr"></param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        public static bool PayForAgentRegist(int uid, decimal payamount, int dimond_number, decimal rebate_amount, decimal parent1_amount, decimal parent2_amount, string encrypt_key, string out_trade_no, out string output_msg)
        {
            // 生成序列表
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            DataTable dtTemp = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(string.Format("select top 1 parent1_uid, parent2_uid from t_user where user_id={0}", uid));
            if (dtTemp.Rows.Count < 1)
            {
                output_msg = "";
                return false;
            }
            int pid1 = int.Parse(dtTemp.Rows[0]["parent1_uid"].ToString());
            int pid2 = int.Parse(dtTemp.Rows[0]["parent2_uid"].ToString());

            output_msg = string.Empty;
            int ireturn = 0;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddInputInteger("@pint_uid", uid);
            dbParams.AddInputDecimal("@pdec_amount", payamount);
            dbParams.AddInputInteger("@pint_dimond_number", dimond_number);
            dbParams.AddInputDecimal("@pdec_rebate_amount", rebate_amount);
            dbParams.AddInputDecimal("@pdec_parent1_amount", parent1_amount);
            dbParams.AddInputDecimal("@pdec_parent2_amount", parent2_amount);
            dbParams.AddInputString("@pstr_serialno", SerialNoUtil.MakeTradeSerialNo(uid, (double)payamount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_serialno_parent1", SerialNoUtil.MakeTradeSerialNo(pid1, (double)parent1_amount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_serialno_parent2", SerialNoUtil.MakeTradeSerialNo(pid2, (double)parent2_amount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_out_trade_no", out_trade_no);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            System.Data.Common.DbParameter[] outParams = DbFactory.Instance.ExecuteProcedureNonQuery("proc_agent_regist_v4", dbParams.ToArray());
            foreach (System.Data.Common.DbParameter p in outParams)
            {
                if (p.ParameterName == "@pstr_output")
                {
                    output_msg = p.Value.ToString();
                    continue;
                }
                if (p.ParameterName == "@return")
                {
                    ireturn = int.Parse(p.Value.ToString());
                    continue;
                }
            }
            bool result = ireturn > 0;
            return result;
        }
        /// <summary>
        /// 购买钻石支付流程
        /// <para>为自己购买(payforme)或为别人购买(payforother)</para>
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="payfor">为自己购买(payforme)或为别人购买(payforother)</param>
        /// <param name="game_coin_name"></param>
        /// <param name="game_id"></param>
        /// <param name="game_nickname"></param>
        /// <param name="payamount"></param>
        /// <param name="dimond_number"></param>
        /// <param name="parent1_amount"></param>
        /// <param name="parent2_amount"></param>
        /// <param name="encrypt_key"></param>
        /// <param name="out_trade_no"></param>
        /// <param name="pay_channel"></param>
        /// <param name="paramstr"></param>
        /// <param name="output_msg"></param>
        /// <returns></returns>
        public static bool PayForByDimond(int uid, string payfor, int game_mact_id, int game_id, string game_nickname, decimal payamount, int dimond_number, decimal parent1_amount, decimal parent2_amount, string encrypt_key, string out_trade_no, out string output_msg)
        {
            // 生成序列表
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            DataTable dtTemp = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteDataTable(string.Format("select top 1 parent1_uid, parent2_uid from t_user where user_id={0}", uid));
            if (dtTemp.Rows.Count < 1)
            {
                output_msg = "";
                return false;
            }
            int pid1 = int.Parse(dtTemp.Rows[0]["parent1_uid"].ToString());
            int pid2 = int.Parse(dtTemp.Rows[0]["parent2_uid"].ToString());

            output_msg = string.Empty;
            int ireturn = 0;
            DbFactory.Init(AppInfo.conn_yule8x_agent, true);
            DbParams dbParams = DbFactory.CreateParams();
            dbParams.AddInputInteger("@pint_uid", uid);
            dbParams.AddInputString("@pstr_payfor", payfor);
            dbParams.AddInputDecimal("@pdec_amount", payamount);
            dbParams.AddInputInteger("@pint_dimond_number", dimond_number);
            dbParams.AddInputInteger("@pint_game_mact_id", game_mact_id);
            dbParams.AddInputInteger("@pint_game_id", game_id);
            dbParams.AddInputString("@pstr_game_nickname", game_nickname);
            dbParams.AddInputDecimal("@pdec_parent1_amount", parent1_amount);
            dbParams.AddInputDecimal("@pdec_parent2_amount", parent2_amount);
            dbParams.AddInputString("@pstr_serialno", SerialNoUtil.MakeTradeSerialNo(uid, (double)payamount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_serialno_parent1", SerialNoUtil.MakeTradeSerialNo(pid1, (double)parent1_amount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_serialno_parent2", SerialNoUtil.MakeTradeSerialNo(pid2, (double)parent2_amount, timestamp, encrypt_key));
            dbParams.AddInputString("@pstr_out_trade_no", out_trade_no);
            dbParams.AddOutput<string>("@pstr_output");
            dbParams.AddReturn("@return");
            try
            {
                System.Data.Common.DbParameter[] outParams = DbFactory.Init(AppInfo.conn_yule8x_agent).ExecuteProcedureNonQuery("proc_buy_dimond_v4", dbParams.ToArray());
                foreach (System.Data.Common.DbParameter p in outParams)
                {
                    if (p.ParameterName == "@pstr_output")
                    {
                        output_msg = p.Value.ToString();
                        continue;
                    }
                    if (p.ParameterName == "@return")
                    {
                        ireturn = int.Parse(p.Value.ToString());
                        continue;
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            bool result = ireturn > 0;
            return result;
        }

    }
}